﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Globalization;

namespace US.DateSelectorControl
{
    [TemplatePart(Name = "PART_CMBYear", Type = typeof(ComboBox))]
    [TemplatePart(Name = "PART_CMBMonth", Type = typeof(ComboBox))]
    [TemplatePart(Name = "PART_CMBDay", Type = typeof(ComboBox))]

    public class DateSelector : Control
    {
        #region private members

        private ComboBox part_cmbYear;
        private ComboBox part_cmbMonth;
        private ComboBox part_cmbDay;
        private int currentYear = DateTime.Now.Year;
        private bool _isLongYear = false;

        #endregion

        public DateSelector()
        {
            this.DefaultStyleKey = typeof(DateSelector);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            part_cmbYear = GetTemplateChild("PART_CMBYear") as ComboBox;
            part_cmbMonth = GetTemplateChild("PART_CMBMonth") as ComboBox;
            part_cmbDay = GetTemplateChild("PART_CMBDay") as ComboBox;

            part_cmbYear.SelectionChanged += new SelectionChangedEventHandler(part_cmbYear_SelectionChanged);
            part_cmbDay.SelectionChanged += new SelectionChangedEventHandler(part_cmbDay_SelectionChanged);
            part_cmbMonth.SelectionChanged += new SelectionChangedEventHandler(part_cmbMonth_SelectionChanged);
            
            this.LostFocus += new RoutedEventHandler(DateSelectionControl_LostFocus);

            if (part_cmbDay == null || part_cmbYear == null || part_cmbMonth == null)
            {
                throw new NullReferenceException("Template Parts not Available");
            }

            MonthList = new ObservableCollection<string>();
            MonthList.Add("Month:");

            foreach (string mnth in CultureInfo.CurrentCulture.DateTimeFormat.MonthNames)
            {
                MonthList.Add(mnth);
            }

            part_cmbMonth.SelectedIndex = 0;
            
            YearList = new ObservableCollection<object>();

            YearList.Add("Year:");
            for (int i = currentYear; i >= 1905; i--)
            {
                YearList.Add(i);
            }

            part_cmbYear.SelectedIndex = 0;

            DayList = new ObservableCollection<object>();
            DayList.Add("Day:");
            for (int j = 1; j < 32; j++)
            {
                DayList.Add(j);
            }

            part_cmbDay.SelectedIndex = 0;

            
        }

        void DateSelectionControl_LostFocus(object sender, RoutedEventArgs e)
        {

            int a = 2;
        }

        void part_cmbMonth_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Month = (int)part_cmbMonth.SelectedIndex;

            switch (Month)
            {
                case 0:
                    MonthString = "Month:";
                    break;
                case 1:
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    if (!(DayList.Contains(31)))
                    {
                        DayList.Add(31);
                    }
                    break;
                case 2:

                    if (_isLongYear == true)
                    {
                        if (part_cmbDay.SelectedIndex != 0)
                        {
                            if ((int)part_cmbDay.SelectedValue == 31 || (int)part_cmbDay.SelectedValue == 30)
                            {
                                part_cmbDay.SelectedIndex = 0;
                            }
                        }
                        if (DayList.Contains(31))
                        {
                            DayList.Remove(31);
                        }
                        if (DayList.Contains(30))
                        {
                            DayList.Remove(30);
                        }
                    }
                    else
                    {
                        if (part_cmbDay.SelectedIndex != 0)
                        {
                            if ((int)part_cmbDay.SelectedValue == 31 || (int)part_cmbDay.SelectedValue == 30 || (int)part_cmbDay.SelectedValue == 29)
                            {
                                part_cmbDay.SelectedIndex = 0;
                            }
                        }
                        if (DayList.Contains(31))
                        {
                            DayList.Remove(31);
                        }
                        if (DayList.Contains(30))
                        {
                            DayList.Remove(30);
                        }
                        if (DayList.Contains(29))
                        {
                            DayList.Remove(29);
                        }
                    }
                    break;
                case 3:
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    if (!(DayList.Contains(31)))
                    {
                        DayList.Add(31);
                    }
                    break;
                case 4:
                    if (part_cmbDay.SelectedIndex != 0)
                    {
                        if ((int)part_cmbDay.SelectedValue == 31)
                        {
                            part_cmbDay.SelectedIndex = 0;
                        }
                    }
                    if (DayList.Contains(31))
                    {
                        DayList.Remove(31);
                    }
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    break;
                case 5:
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    if (!(DayList.Contains(31)))
                    {
                        DayList.Add(31);
                    }
                    break;
                case 6:
                    if (part_cmbDay.SelectedIndex != 0)
                    {
                        if ((int)part_cmbDay.SelectedValue == 31)
                        {
                            part_cmbDay.SelectedIndex = 0;
                        }
                    }
                    if (DayList.Contains(31))
                    {
                        DayList.Remove(31);
                    }
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    break;
                case 7:
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    if (!(DayList.Contains(31)))
                    {
                        DayList.Add(31);
                    }
                    break;
                case 8:

                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    if (!(DayList.Contains(31)))
                    {
                        DayList.Add(31);
                    }
                    break;
                case 9:
                    if (part_cmbDay.SelectedIndex != 0)
                    {
                        if ((int)part_cmbDay.SelectedValue == 31)
                        {
                            part_cmbDay.SelectedIndex = 0;
                        }
                    }
                    if (DayList.Contains(31))
                    {
                        DayList.Remove(31);
                    }
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    break;
                case 10:
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    if (!(DayList.Contains(31)))
                    {
                        DayList.Add(31);
                    }
                    break;
                case 11:
                    if (part_cmbDay.SelectedIndex != 0)
                    {
                        if ((int)part_cmbDay.SelectedValue == 31)
                        {
                            part_cmbDay.SelectedIndex = 0;
                        }
                    }
                    if (DayList.Contains(31))
                    {
                        DayList.Remove(31);
                    }
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    break;
                case 12:
                    if (!(DayList.Contains(29)))
                    {
                        DayList.Add(29);
                    }
                    if (!(DayList.Contains(30)))
                    {
                        DayList.Add(30);
                    }
                    if (!(DayList.Contains(31)))
                    {
                        DayList.Add(31);
                    }
                    break;

            }


            if (part_cmbDay.SelectedIndex != 0 & part_cmbMonth.SelectedIndex != 0 & part_cmbYear.SelectedIndex != 0)
            {
                DateValue = new DateTime(Year, Month, Day);
            }
        }

        void part_cmbDay_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            object obj = part_cmbDay.SelectedValue;
            if (Convert.ToString(obj) != "Day:")
            {
                Day = Convert.ToInt32(obj);
            }

            if (part_cmbDay.SelectedIndex != 0 & part_cmbMonth.SelectedIndex != 0 & part_cmbYear.SelectedIndex != 0)
            {
                DateValue = new DateTime(Year, Month, Day);
            }
        }

        void part_cmbYear_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _isLongYear = false;
            object obj = part_cmbYear.SelectedValue;
            if (Convert.ToString(obj) != "Year:")
            {
                Year = Convert.ToInt32(obj);

                if (Year % 4 == 0)
                {
                    _isLongYear = true;
                    if (Month != 0)
                    {
                        if (Month == 2)
                        {
                            if (!(DayList.Contains(29)))
                            {
                                DayList.Add(29);
                                part_cmbDay.ItemsSource = DayList;
                            }
                        }
                    }
                }
                else
                {
                    if (Month == 2)
                    {
                        if (Day == 29)
                        {
                            part_cmbDay.SelectedIndex = 0;
                        }

                        if (DayList.Contains(29))
                        {
                            DayList.Remove(29);
                        }
                    }
                }
            }

            if (part_cmbDay.SelectedIndex != 0 & part_cmbMonth.SelectedIndex != 0 & part_cmbYear.SelectedIndex != 0)
            {
                DateValue = new DateTime(Year, Month, Day);
            }
        }

        #region dependence properties

        private ObservableCollection<string> MonthList
        {
            get { return (ObservableCollection<string>)GetValue(MonthListProperty); }
            set { SetValue(MonthListProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        private static readonly DependencyProperty MonthListProperty =
            DependencyProperty.Register("MonthList", typeof(ObservableCollection<string>), typeof(DateSelector), new PropertyMetadata(null));

        private ObservableCollection<object> YearList
        {
            get { return (ObservableCollection<object>)GetValue(YearListProperty); }
            set { SetValue(YearListProperty, value); }
        }

        // Using a DependencyProperty as the backing store for YearList.  This enables animation, styling, binding, etc...
        private static readonly DependencyProperty YearListProperty =
            DependencyProperty.Register("YearList", typeof(ObservableCollection<object>), typeof(DateSelector), new PropertyMetadata(null));

        private ObservableCollection<object> DayList
        {
            get { return (ObservableCollection<object>)GetValue(DayListProperty); }
            set { SetValue(DayListProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DayList.  This enables animation, styling, binding, etc...
        private static readonly DependencyProperty DayListProperty =
            DependencyProperty.Register("DayList", typeof(ObservableCollection<object>), typeof(DateSelector), new PropertyMetadata(null));

        public DateTime DateValue
        {
            get { return (DateTime)GetValue(DateValueProperty); }
            set
            {
                SetValue(DateValueProperty, value);
                if (DateValue.Month == 1)
                {
                    MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[0];
                }
                if (DateValue.Month == 2)
                {
                   MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[1];
                }
                if (DateValue.Month == 3)
                {                  
                    MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[2];
                }
                if (DateValue.Month == 4)
                {                   
                    MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[3];
                }
                if (DateValue.Month == 5)
                {
                   MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[4];
                }
                if (DateValue.Month == 6)
                {
                   MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[5];
                }
                if (DateValue.Month == 7)
                {
                   MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[6];
                }
                if (DateValue.Month == 8)
                {                   
                    MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[7];
                }
                if (DateValue.Month == 9)
                {
                  MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[8];
                }
                if (DateValue.Month == 10)
                {
                  MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[9];
                }
                if (DateValue.Month == 11)
                {
                  MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[10];
                }
                if (DateValue.Month == 12)
                {
                  MonthString = CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[11];
                }
               
            }
        }

        // Using a DependencyProperty as the backing store for DateValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DateValueProperty =
            DependencyProperty.Register("DateValue", typeof(DateTime), typeof(DateSelector), new PropertyMetadata(null));

        private int Year
        {
            get { return (int)GetValue(YearProperty); }
            set { SetValue(YearProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Year.  This enables animation, styling, binding, etc...
        private static readonly DependencyProperty YearProperty =
            DependencyProperty.Register("Year", typeof(int), typeof(DateSelector), new PropertyMetadata(0));

        private string MonthString
        {
            get { return (string)GetValue(MonthStringProperty); }
            set { SetValue(MonthStringProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Month.  This enables animation, styling, binding, etc...
        private static readonly DependencyProperty MonthStringProperty =
            DependencyProperty.Register("MonthString", typeof(string), typeof(DateSelector), new PropertyMetadata(null));

        private int Month
        {
            get { return (int)GetValue(MonthProperty); }
            set { SetValue(MonthProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Month.  This enables animation, styling, binding, etc...
        private static readonly DependencyProperty MonthProperty =
            DependencyProperty.Register("Month", typeof(int), typeof(DateSelector), new PropertyMetadata(0));

        private int Day
        {
            get { return (int)GetValue(DayProperty); }
            set { SetValue(DayProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Day.  This enables animation, styling, binding, etc...
        private static readonly DependencyProperty DayProperty = DependencyProperty.Register("Day", typeof(int), typeof(DateSelector), new PropertyMetadata(0));

        #endregion
    }
}
